package legumes.client.ui.widgets.window;

import legumes.client.resources.PNResources;
import legumes.client.ui.widgets.label.LoadingLabel;
import legumes.client.ui.widgets.map.MapDrawingCircleUtils;
import legumes.client.ui.widgets.map.MapFactory;
import legumes.shared.domain.HomePlaceDelivery;
import legumes.shared.domain.PlaceDelivery;
import legumes.shared.domain.PostalAdress;

import com.google.gwt.core.client.GWT;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.event.MarkerDragEndHandler;
import com.google.gwt.maps.client.geocode.Geocoder;
import com.google.gwt.maps.client.geocode.LatLngCallback;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.Icon;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.ui.Image;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.WidgetCanvas;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.events.CloseClientEvent;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.CheckboxItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;

public abstract class MapConfirmationOfPostalAdressWindow extends Window {

	private PostalAdress pa;
	private LatLng adressPostalLatLng;
	private ButtonItem biValidate;
	private ButtonItem biCancel;
	private Marker marker;
	private MapWidget map;
	private int windowHeight;
	
	private CheckboxItem cbHomeDelivering;
	private TextItem tbHomeDeliveringCircleRadius;
	
	private MapDrawingCircleUtils mapDrawingCircleUtils;
	
	private LoadingLabel loadingLab;
	private PlaceDelivery pdToEdit;
	
	/**
	 * Automatically show when map is loaded
	 * @param pa_
	 */
	public MapConfirmationOfPostalAdressWindow(PostalAdress pa_) {
		this(pa_, 640, 480, null);
	}
	
	/**
	 * Automatically show when map is loaded
	 * @param pa_
	 */
	public MapConfirmationOfPostalAdressWindow(
			PostalAdress pa_, int windowWidth_, int windowHeight_,
			PlaceDelivery pdToEdit_) {
		super();
		pa = pa_;
		pdToEdit = pdToEdit_;
		setTitle("<img src=\"" + PNResources.INSTANCE.deliveryIcon().getURL() + "\" />&nbsp;Confirmer la nouvelle adresse");
		setWidth(windowWidth_);
		windowHeight = windowHeight_;
		setHeight(windowHeight);
		setShowCloseButton(true);
		setShowMinimizeButton(false);
		setAutoCenter(true);
		setIsModal(true);
		setShowModalMask(false);
		addCloseClickHandler(new CloseClickHandler() {  
            public void onCloseClick(CloseClientEvent event) {  
            	MapConfirmationOfPostalAdressWindow.this.destroy();  
            }  
        });

		MapFactory.getInstance().loadMapLibrary(
				new Runnable() {
					public void run() {
						addItem( buildUi() );
						show();
					}
				}
		);
	}

	protected VLayout buildUi() {
		VLayout mainPanel = new VLayout();
		mainPanel.setWidth100();
		mainPanel.setHeight100();
		mainPanel.setMargin(10);
		
		Label labTitle = new Label(
				"<h3>Confirmer l'emplacement de votre adresse de livraison :</h3>" +
				"<i>Positionner le marker " +
				"<img src=\"" + PNResources.INSTANCE.gmapDeliveringAtMarketIcon().getURL() + "\" />" + 
				"sur le lieux exact de livraison, puis valider.</i>");
		labTitle.setWidth100();
		labTitle.setAutoHeight();

		HLayout hlTitle = new HLayout();
		hlTitle.setWidth100();
		loadingLab = new LoadingLabel();
		showLoading();
		hlTitle.setMembers(labTitle, new WidgetCanvas(loadingLab));
		
		String adressPostal = pa.toStringAdressPostal();
		Geocoder gc = new Geocoder();
		gc.getLatLng(adressPostal, new LatLngCallback() {
			
			@Override
			public void onSuccess(LatLng point) {
				onAdressPositionned(point);
			}
			
			@Override
			public void onFailure() {
				onAdressPositionned(null);
			}
		});
		
		map = MapFactory.getInstance().createMapWidget(LatLng.newInstance(43.6, 1.46), getWidth()-50, windowHeight-200);
		map.setZoomLevel(7);
		HLayout hl = new HLayout();
		hl.setWidth100();
		Label labAdress = new Label( pa.toStringHTMLAdressPostal());
		labAdress.setWidth("*");
		labAdress.setAutoHeight();
		hl.setMembers(labAdress, createValidateButtons());
		
		mainPanel.setMembers(hlTitle, 
				buildHomeDeliveringPanel(), 
				hl, 
				new WidgetCanvas(map));
		
		return mainPanel;
	}
	
	private HLayout buildHomeDeliveringPanel(){
		HLayout hPanel = new HLayout();
	    hPanel.setMembersMargin(3);
	    hPanel.setWidth("*");
	    hPanel.setHeight("25px");
	    

	    boolean isHomePlaceDelivery = pdToEdit instanceof HomePlaceDelivery;
	    int kmRadius = 50;
		if(isHomePlaceDelivery){
			kmRadius = ((HomePlaceDelivery) pdToEdit).getRadiusKm();
		}
		
		cbHomeDelivering = new CheckboxItem("cbHomeDelivering", "Livraison à domicile");
		cbHomeDelivering.setColSpan(2);
		cbHomeDelivering.setWidth("190px");
		cbHomeDelivering.setTooltip("Cochez cette case uniquement si souhaitez proposer un service de livriason à domicile à vos clients.");
		cbHomeDelivering.setValue(isHomePlaceDelivery);
		cbHomeDelivering.addChangedHandler(new ChangedHandler() {
			
			@Override
			public void onChanged(ChangedEvent event) {
				if( isDeliveringAtHome() ){
					onDeliveringAtHomeSelected();
				} else {
					onDeliveringAtMarketSelected();
				}
			}
		});
		
		tbHomeDeliveringCircleRadius = new TextItem("tbHomeDeliveringCircleRadius");
		tbHomeDeliveringCircleRadius.setHint("km");
		tbHomeDeliveringCircleRadius.setWidth(30);
		tbHomeDeliveringCircleRadius.setShowTitle(false);
		tbHomeDeliveringCircleRadius.setStartRow(false);
		tbHomeDeliveringCircleRadius.setColSpan(2);
		tbHomeDeliveringCircleRadius.addChangedHandler(new ChangedHandler() {
			
			@Override
			public void onChanged(ChangedEvent event) {
				try{
					int radius = Integer.parseInt(tbHomeDeliveringCircleRadius.getValueAsString());
					mapDrawingCircleUtils.setRadius(radius);
					mapDrawingCircleUtils.drawCircle();
				} catch(Exception e_){
					GWT.log("Error tbHomeDeliveringCircleRadius onValueChange : Radius str =" + tbHomeDeliveringCircleRadius.getValue());
				}
			}
		});
		tbHomeDeliveringCircleRadius.setValue("" + kmRadius);
		
	    DynamicForm df = new DynamicForm();
	    df.setNumCols(6);
	    df.setWidth100();
	    df.setItems(cbHomeDelivering, tbHomeDeliveringCircleRadius );
	    
		hPanel.setMembers(
				new WidgetCanvas( new Image(PNResources.INSTANCE.deliveryIcon()) ),
				df
		);
		
		return hPanel;
	}
	
	private void onDeliveringAtHomeSelected(){
		marker.setImage(PNResources.INSTANCE.gmapDeliveringAtHomeIcon().getURL());
		mapDrawingCircleUtils.setCenter(marker.getLatLng());
		mapDrawingCircleUtils.drawCircle();
	}
	
	private void onDeliveringAtMarketSelected(){
		marker.setImage(PNResources.INSTANCE.gmapDeliveringAtMarketIcon().getURL());
		mapDrawingCircleUtils.setCenter(marker.getLatLng());
		mapDrawingCircleUtils.clearCreatedMapOverlays();
	}
	
	private void onAdressPositionned(LatLng point_){
		LatLng point;
		String moTxt;
		if(point_!=null){
			point = point_;
			moTxt="Votre adresse a été trouvée ici.";
		} else {
			point = LatLng.newInstance(43.6, 1.46);
			moTxt="Votre adresse n'a pas été trouvée. Merci de déplacer le curseur sur votre point de livraison.";
		}
		adressPostalLatLng = point;
		map.setCenter(adressPostalLatLng);
		
		if( marker == null ){
			initMarker(adressPostalLatLng, moTxt);
		}
		
		hideLoading();
	}
	
	private void initMarker(LatLng point_, String moTxt_){
		MarkerOptions markerOptions = MarkerOptions.newInstance();
		markerOptions.setDraggable(true);
		markerOptions.setTitle(moTxt_);
		Icon ic = Icon.DEFAULT_ICON;
		ic.setImageURL(PNResources.INSTANCE.gmapDeliveringAtMarketIcon().getURL());
		markerOptions.setIcon( ic );
		
		marker = new Marker(adressPostalLatLng, markerOptions);
		mapDrawingCircleUtils = new MapDrawingCircleUtils(map, marker.getLatLng(), getRadius(), true){

			@Override
			protected void onCircleResized(int oldRadius_, int newRadius_) {
				super.onCircleResized(oldRadius_, newRadius_);
				if( isDeliveringAtHome() ){
					tbHomeDeliveringCircleRadius.setValue( "" + newRadius_ );
				}
			}
			
		};
		if( pdToEdit != null && cbHomeDelivering.getValueAsBoolean() ){
			onDeliveringAtHomeSelected();
		}
		
		marker.addMarkerDragEndHandler(new MarkerDragEndHandler(){

			@Override
			public void onDragEnd(MarkerDragEndEvent event) {
				if( isDeliveringAtHome() ){
					mapDrawingCircleUtils.setCenter(marker.getLatLng());
					mapDrawingCircleUtils.drawCircle();
				}
			}
			
		});
		map.addOverlay(marker);
		
	}
	
	public void hideLoading(){
		loadingLab.setVisible(false);
	}
	
	public void showLoading(){
		loadingLab.setVisible(true);
	}

	private HLayout createValidateButtons() {
		HLayout hlPanel = new HLayout();
		hlPanel.setMargin(10);
		hlPanel.setAutoHeight();
		
    	biValidate = new ButtonItem("AddToBasket", "Valider");
    	biValidate.setAutoFit(true);
    	biValidate.setColSpan(1);
    	biValidate.setAlign(Alignment.CENTER);
    	biValidate.setStartRow(true);
    	biValidate.setEndRow(false);
    	biValidate.setIcon( PNResources.INSTANCE.addIcon().getURL() );
    	biValidate.addClickHandler( new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				onBiValidateClicked(isDeliveringAtHome(), getRadius());
			}
		} );
    	
    	biCancel = new ButtonItem("RemoveFromBasket", "Annuler");
    	biCancel.setIcon( PNResources.INSTANCE.cancelIcon().getURL() );
    	biCancel.setAlign(Alignment.CENTER);
    	biCancel.setStartRow(false);
    	biCancel.setEndRow(false);
    	biCancel.addClickHandler( new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				MapConfirmationOfPostalAdressWindow.this.destroy();
			}
		});
    	DynamicForm df = new DynamicForm();
    	df.setNumCols(4);
    	df.setItems(biValidate, biCancel);
    	hlPanel.setMembers(df);
		return hlPanel;
	}
	
	private int getRadius(){
		return Integer.parseInt(tbHomeDeliveringCircleRadius.getValueAsString());
	}
	
	private boolean isDeliveringAtHome(){
		return cbHomeDelivering.getValueAsBoolean();
	}

	private void onBiValidateClicked(boolean isDeliveringAtHome_, int homeDeliveringAreaRadius_){
		if(isDeliveringAtHome_ && homeDeliveringAreaRadius_<=0){
			SC.say("Veuillez définir une zone de livraison d'au moins 1 km de rayon; ou décocher la possibilité de livrer à domicile.");
		} else {
			onValidateAction(isDeliveringAtHome_, homeDeliveringAreaRadius_);
		}
	}
	
	abstract void onValidateAction(boolean isDeliveringAtHome_, int homeDeliveringAreaRadius_);
	
	
	public legumes.shared.domain.LatLng getLatLng(){
		return new legumes.shared.domain.LatLng(
				marker.getLatLng().getLatitude(),
				marker.getLatLng().getLongitude());
	}
	
}
